2016-12-16 3 views
1

Учитывая, что теперь можно обрабатывать двоичные данные в Amazon Api Gateway и Amazon Lambda, я хотел попытаться создать конечную точку Amazon Lambda, которая вернула электронную таблицу Excel. Это вполне возможно сделать, используя node/js, как показано here. К сожалению, каждый раз, когда я пытаюсь сделать это с помощью Java, он падает на куски.Как вернуть двоичные данные из AWS Lambda, написанные на Java

Моя первоначальная попытка состояла в том, чтобы создать простую книгу, используя apache XSSFWorkbook, записать ее в выходной поток, предоставленный RequestStreamHandler, и сделать.

import com.amazonaws.services.lambda.runtime.Context; 
import com.amazonaws.services.lambda.runtime.RequestStreamHandler; 
import org.apache.poi.ss.usermodel.Workbook; 
import org.apache.poi.xssf.usermodel.XSSFWorkbook; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

public class FileRequestHandler implements RequestStreamHandler { 
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) 
      throws IOException { 
     Workbook wb = new XSSFWorkbook(); 
     String sheetName = "Problem sheet"; 
     wb.createSheet(sheetName); 
     wb.write(outputStream); 
    } 
} 

При тестировании локально поток вывода может быть передан в файл, что приведет к действительному выходному файлу excel.

import com.amazonaws.util.StringInputStream; 
import org.junit.Test; 

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 

public class FileRequestHandlerTest { 

    @Test 
    public void shouldCreateExcelFile() throws IOException { 
     FileRequestHandler fileRequestHandler = new FileRequestHandler(); 
     InputStream inputStream = new StringInputStream("hello world"); 
     String fileName = "FileRequestLambda"; 
     String path = fileName + ".xlsx"; 
     FileOutputStream fileOutputStream = new FileOutputStream(path); 

     fileRequestHandler.handleRequest(inputStream, fileOutputStream, TestUtils.createContext()); 
     fileOutputStream.close(); 
    } 
} 

Но когда я запускаю его в Amazon Lambda, я получаю искаженный двоичный выход:

PKn��I_rels/.rels���j�0��} 
�{㴃1F�^Ơ�2��l%1I,c�[��3�l 
l�����H��4��R�l��·����q}*�2�������;�*�� 
t"�^�l;1W)�N�iD)ejuD�cKz[׷:}g����@:� 
�3����4�7N�s_ni�G�M*7�����2R�+�� �2�/�����b��mC�Pp�ֱ$POyQ�抒�DsZ��IС�'un���~�PK����OPKn��I[Content_Types].xml�SMO1��+6��m��1���G%��β 
�J[���MDL0�S;yo�{3i�Ӎ5�c��5lć�B'��nѰ��S}˪��)0�aÜg��`<�L��԰.�p'D�ZH�t��>Z�Tƅ ��@q=��]F��\4�=`+���P�!-!S.�v�@��+�����N�tEV=nHe7���S,;K]_h7Q+�W8߶Z��re��c�U�����}�����g�&A��,���H�$�B<��`�"�Jb���"���I�N�1���A���CI�#��܂v��?|\�{��`�b������$�c�D��|2�PKKB�>'PKn��IdocProps/app.xmlM�� 
�0D�~EȽ��ADҔ���A? ��6�lB�J?ߜ���0���ͯ��)�@��׍H6���V>��$;�SC 
;̢(�ra�g�l�&�e��L!y�%��49��`_���4G���F��J��Wg 
�GS�b���� 
~�PK�|wؑ�PKn��IdocProps/core.xmlm��J�0F��!�m�V����(���Ż��m��!�v}{ӺVP/g��a��wG5�wp~4��4�1-�u���n��c�גOFC����6��e�888c��<�홰 
B��/P�g��q�b��!��'��W�)��" 
�<p�S��I)Ŧ�onZR�@��Ќ�6�S�߅u��G?n�<��\�\����ۛ���t���p|��f� Q4��ac&ߓ��������i��"�UG+vV��z�ɯ���U�^�[email protected]�����IM�$�&�PK����PKn��Ixl/sharedStrings.xml=�A� ツ��.z0Ɣ�`������,�����q2��o�ԇ���N�E��x5�z>�W���(R�K���^4{�����ŀ�5��y�V����y�m�XV�\�.��j����� 
8�PKp��&x�PKn��I 
xl/styles.xml���n� ��>bop2TQ��P)U��RWb�6*�����ӤS�Nw�s���3ߍ֐���t��(l��������ҝx�[email protected]$ɀ��}��3c���ʰr`:i��2��w,� 
�d 
�T��R#�voc �;c�iE���Û��E<|��4Iɣ�����F#��n���B�z�F���y�j3y��yҥ�jt>���2��Lژ�!6��2F��OY��[email protected]�!���G��������1�t��y��p��" n����u�����a�ΦDi�9�&#��%I��9��}���cK��T��$?������`J������7���o��f��M|PK�[email protected]�PKn��Ixl/workbook.xml���N�0��<��wj�E�8��J��P�;�����hmZ'Q�#����~;���;vCJ6 �Fà���"��|x|�}���#]����C�0�<֜'=�WiG��#y���O#�[email protected]������+`!��F�{��-�O�!/B�r)�;&h�����zOz�o����xO��I2����YuĔ��s�u��<J8Q�z6��Qm�:�,�c��Z�����PK1����dPKn��Ixl/_rels/workbook.xml.rels��[email protected]���0�nv-�R�^����0$����$dƯo���R�OC�ރ�-��������@Sՠ(�����ܼ?��b��p�����d�AJ�¾O� 
#�/�޴f�iD�b�P6m�#Jy�N'�[�HO��E�k����3�W���ܑ`���Zri㪐����?�ض��e�������7p�wj�W5r���]������=�|���<:�[p��7�O�PK��4��9PKn��Ixl/worksheets/sheet1.xmleP�N�0���މ�V��THU$���$��j���[��c�����3��-v�nT���/a����7�Zߗ��z���]uQ���0 ��zJD�[�C3�3!� }|鈝�H��ab4�br�^���v�z���:�)P1v%ܭ@W�"|�8�?X�ܚ���C[B�'�~��ȅO������Tyb�bgN�<�|��$��ƙ��{#&����h��>��D�Ű�z�#��6��8�LF�dQ����,4�xS����/PK�_�Y�lPKn��I����O_rels/.relsPKn��IKB�>'[Content_Types].xmlPKn��I�|wؑ��docProps/app.xmlPKn��I����mdocProps/core.xmlPKn��Ip��&x��xl/sharedStrings.xmlPKn��I�[email protected]� 
nxl/styles.xmlPKn��I1����d�xl/workbook.xmlPKn��I��4��9xl/_rels/workbook.xml.relsPKn��I�_�Y�l$ xl/worksheets/sheet1.xmlPK  ?Z 

Выхода около 5KB в размерах, в то время как выход на моем локальном компьютере около 3KB в размерах. Это, по-видимому, проблема с двоичным выходом в целом для Java на Amazon Lambda. Когда я запускаю некоторый код, который записывает изображение в выходную строку, он также работает локально, но приводит к отображению в два раза размера и искажению при запуске с Amazon Lambda.

import com.amazonaws.services.lambda.runtime.Context; 
import com.amazonaws.services.lambda.runtime.RequestStreamHandler; 

import java.io.*; 
import java.net.URL; 

public class ImageRequestHandler implements RequestStreamHandler { 
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) 
      throws IOException { 
     String address = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/AmazonWebservices_Logo.svg/580px-AmazonWebservices_Logo.svg.png"; 
     URL url = new URL(address); 

     InputStream in = new BufferedInputStream(url.openStream()); 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     byte[] buf = new byte[1024]; 
     int n; 
     while (-1!=(n=in.read(buf))) 
     { 
      out.write(buf, 0, n); 
     } 
     out.close(); 
     in.close(); 
     byte[] response = out.toByteArray(); 
     outputStream.write(response); 
    } 
} 

типам был входных и выходных потоков являются:

lambdainternal.util.NativeMemoryAsInputStream lambdainternal.util.LambdaByteArrayOutputStream

Помощь?

+0

Рассмотрим, действительно ли вы хотите, чтобы подтолкнуть все первенствовать файл через результат вашей лямбды. Может ли это иметь смысл, чтобы сдать его на s3 и вернуть назначенный URL? Это будет обрабатывать файлы excel «любого размера» - [полезная нагрузка лямбда-ответа может быть только 6M] (http://docs.aws.amazon.com/lambda/latest/dg/limits.html). Это также будет поддерживать вашу лямбду (написание на S3 будет довольно надежным и очень быстрым) и оставить передачу данных в руках S3, которая очень хороша в этом. Вы также можете загрузить файл снова в случае отказа без другого вызова. –

ответ

0

У меня была та же проблема с возвратом изображения JPG от Amazon Lambda, и я нашел обход. Вам нужно кодировать выходной поток с кодировкой base64:

OutputStream encodedStream = Base64.getEncoder().wrap(outputStream); 
encodedStream.write(response); 
encodedStream.close(); 

Затем вам нужно обновить метод реагирования и интеграции отклика вашей функции, как описано здесь: AWS Gateway API base64Decode produces garbled binary?

Смежные вопросы