Spring для Android, процесс загрузки файлов

Я использую Spring для Android в качестве шаблона REST для удаленных вызовов в приложении для Android.

В настоящее время работает над загрузкой изображений на сервер.

Я придумал что-то вроде этого:

public Picture uploadPicture(String accessToken, String fileToUpload) throws RestClientException {
 RestTemplate rest = new RestTemplate();
 FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
 formConverter.setCharset(Charset.forName("UTF8"));
 CustomGsonHttpMessageConverter jsonConverter = new CustomGsonHttpMessageConverter();
 rest.getMessageConverters().add(formConverter);
 rest.getMessageConverters().add(jsonConverter);
 String uploadUri = AppConfig.ROOT_URL.concat(AppConfig.ADD_PHOTO);
 HashMap<string, object=""> urlVariables = new HashMap<string, object="">();
 urlVariables.put("accessToken", accessToken);
 HttpHeaders httpHeaders = new HttpHeaders();
 httpHeaders.setAccept(Collections.singletonList(MediaType.parseMediaType("application/json")));
 MultiValueMap<string, object=""> parts = new LinkedMultiValueMap<string, object="">();
 parts.add("picture", new FileSystemResource(fileToUpload));
 Picture response = rest.postForObject(uploadUri, parts, Picture.class, urlVariables);
 return response;
}
</string,></string,></string,></string,>

который работает нормально, но теперь я хочу получать обновления от него.

Кто-нибудь знает, возможно ли это и как это сделать?

Заранее спасибо:)

2 ответа

Итак, у меня была такая же проблема, и я решил изучить источники Spring -Android. После много рытья я узнал, что мне нужно расширить. Получилось некоторое вдохновение из этой .

ProgressListener

public interface ProgressListener {
 void transferred(long num);
}

CountingInputStream

public class CountingInputStream extends FileInputStream {
 private final ProgressListener listener;
 private long transferred;
 public CountingInputStream(File file, ProgressListener listener) throws FileNotFoundException {
 super(file);
 this.listener = listener;
 this.transferred = 0;
 }
 @Override
 public int read(byte[] buffer) throws IOException {
 int bytesRead = super.read(buffer);
 if (bytesRead != -1) {
 this.transferred += bytesRead;
 }
 this.listener.transferred(this.transferred);
 return bytesRead;
 }
}

ListenerFileSystemResource

public class ListenerFileSystemResource extends FileSystemResource {
 private final ProgressListener listener;
 public ListenerFileSystemResource(File file, ProgressListener listener) {
 super(file);
 this.listener = listener;
 }
 @Override
 public InputStream getInputStream() throws IOException {
 return new CountingInputStream(super.getFile(), listener);
 }
}

SendFileTask

private class SendFileTask extends AsyncTask<string, integer,="" boolean=""> {
 private ProgressListener listener;
 private long totalSize;
 @Override
 protected Boolean doInBackground(String... params) {
 File file = new File(filePath);
 totalSize = file.length();
 listener = new ProgressListener() {
 @Override
 public void transferred(long num) {
 publishProgress((int) ((num / (float) totalSize) * 100));
 }
 };
 ListenerFileSystemResource resource = new ListenerFileSystemResource(file, listener);
 MyResult result = new MyService().uploadFile(resource);
 }
</string,>

MyService

public FileResult uploadFile(ListenerFileSystemResource resource, Long userId, FileType type) {
 String[] pathParams = {ConnectorConstants.FILE_RESOURCE };
 String[] headerKeys = {"manager_user_id"};
 String[] headerValues = {String.valueOf(userId)};
 String[] formKeys = {ConnectorConstants.FILE_FORM_PARAM};
 Object[] formValues = {resource};
 MultiValueMap<string, object=""> body = createMultiValueMap(formKeys, formValues);
 HttpConnector<fileresult> connector = new HttpConnector<fileresult>(FileResult.class);
 return connector.path(pathParams).header(****************(headerKeys, headerValues)).multipart().body(body).post();
}
</fileresult></fileresult></string,>

HttpConnector

public final class HttpConnector<t> {
 public static String API_URL = "https://myapi.com";
 private UriComponentsBuilder builder;
 private RestTemplate template;
 private Class<t> generic;
 private HttpEntity<!--?--> requestEntity;
 private HttpHeaders headers;
 /**
 * 
 * @param generic
 */
 protected HttpConnector(Class<t> generic)
 {
 this.builder = UriComponentsBuilder.fromUriString(API_URL);
 this.template = new RestTemplate();
 this.template.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
 this.generic = generic;
 this.template.getMessageConverters().add(new GsonHttpMessageConverter(getGson()));
 this.headers = new HttpHeaders();
 }
 /**
 * 
 * @param pathSegments
 * @return
 */
 protected HttpConnector<t> path(String[] pathSegments)
 {
 this.builder = builder.pathSegment(pathSegments);
 return this;
 }
 /**
 * 
 * @param headerParams
 * @return
 */
 protected HttpConnector<t> header(List<*************> headerParams)
 {
 for (************* param : headerParams)
 {
 headers.add(param.getName(), param.getValue());
 }
 return this;
 }
 /**
 * 
 * @param queryParams
 * @return
 */
 protected HttpConnector<t> query(List<*************> queryParams)
 {
 for (************* param : queryParams)
 {
 this.builder = builder.queryParam(param.getName(), param.getValue());
 }
 return this;
 }
 /**
 * 
 * @param body
 * @return
 */
 protected HttpConnector<t> body(MultiValueMap<string, ?="" extends="" object=""> body)
 {
 this.requestEntity = new HttpEntity<object>(body, headers);
 return this;
 }
 /**
 * 
 * @param body
 * @return
 */
 protected HttpConnector<t> body(Object body)
 {
 this.requestEntity = new HttpEntity<object>(body, headers);
 headers.setContentType(MediaType.APPLICATION_JSON);
 return this;
 }
 /**
 * 
 * @return
 */
 protected HttpConnector<t> form()
 {
 headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
 return addFormConverter();
 }
 /**
 * 
 * @return
 */
 protected HttpConnector<t> multipart()
 {
 headers.setContentType(MediaType.MULTIPART_FORM_DATA);
 return addFormConverter();
 }
 /**
 * 
 * @return
 */
 private HttpConnector<t> addFormConverter()
 {
 this.template.getMessageConverters().add(new FormHttpMessageConverter());
 return this;
 }
 /**
 * 
 * @return
 * @throws MeplisNotFoundException 
 */
 protected T post() throws MeplisNotFoundException
 {
 return sendRequest(HttpMethod.POST);
 }
 /**
 * 
 * @return
 * @throws MeplisNotFoundException 
 */
 protected T put() throws MeplisNotFoundException
 {
 return sendRequest(HttpMethod.PUT);
 }
 /**
 * 
 * @return
 * @throws MeplisNotFoundException 
 */
 protected T get() throws MeplisNotFoundException
 {
 return sendRequest(HttpMethod.GET);
 }
 /**
 * 
 * @param method
 * @return
 * @throws MeplisNotFoundException 
 */
 private T sendRequest(HttpMethod method) throws MyServiceNotFoundException
 {
 HttpStatus status = null;
 ResponseEntity<t> response;
 try
 {
 response = template.exchange(toUri(), method, getRequestEntity(), generic);
 status = response.getStatusCode();
 if (HttpStatus.OK.equals(status))
 {
 return response.getBody();
 }
 } catch (HttpClientErrorException e)
 {
 if (HttpStatus.NOT_FOUND.equals(e.getStatusCode()))
 {
 throw new MyServiceNotFoundException();
 }
 else
 {
 Log.e(getClass().toString(), String.format("Error %s request, status[%s]", method.toString(), e.getStatusCode()), e);
 }
 } catch (Exception e)
 {
 Log.e(getClass().toString(), String.format("Error %s request, status: %s", method.toString(), status), e);
 }
 return null;
 }
 /**
 * 
 * @return
 */
 private HttpEntity<!--?--> getRequestEntity()
 {
 if (this.requestEntity == null)
 {
 this.requestEntity = new HttpEntity<object>(headers);
 }
 return requestEntity;
 }
 /**
 * 
 * @return
 */
 private URI toUri()
 {
 return this.builder.build().toUri();
 }
 /**
 * 
 * @return
 */
 private Gson getGson()
 {
 return new GsonBuilder().create();
 }
 /**
 * 
 * @return
 */
 public HttpHeaders getHeaders()
 {
 return headers;
 }
}
<p>И я использую <span> ListenerFileSystemResource</span> вместо <span> FileSystemResource</span> и работает. Надеюсь, это будет полезно для кого-то в будущем, так как я не нашел никакой информации об этом для рамки Spring.</p></object></t></t></t></t></object></t></object></string,></t></*************></t></*************></t></t></t></t></t>


Вам необходимо переопределить FormHttpMessageConverter и ResourceHttpMessageConverter:

public class ProgressFormHttpMessageConverter extends FormHttpMessageConverter {
 OnProgressListener mOnProgressListener;
 public ProgressFormHttpMessageConverter() {
 super();
 List<httpmessageconverter<?>> partConverters = new ArrayList<httpmessageconverter<?>>();
 partConverters.add(new ByteArrayHttpMessageConverter());
 StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
 stringHttpMessageConverter.setWriteAcceptCharset(false);
 partConverters.add(stringHttpMessageConverter);
 partConverters.add(new ProgressResourceHttpMessageConverter();
 setPartConverters(partConverters);
 }
 public ProgressFormHttpMessageConverter setOnProgressListener(OnProgressListener listener) {
 mOnProgressListener = listener;
 return this;
 }
 class ProgressResourceHttpMessageConverter extends ResourceHttpMessageConverter {
 @Override
 protected void writeInternal(Resource resource, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
 InputStream inputStream = resource.getInputStream();
 OutputStream outputStream = outputMessage.getBody();
 byte[] buffer = new byte[StreamUtils.BUFFER_SIZE];
 long contentLength = resource.contentLength();
 int byteCount = 0;
 int bytesRead = -1;
 while ((bytesRead = inputStream.read(buffer)) != -1) {
 outputStream.write(buffer, 0, bytesRead);
 byteCount += bytesRead;
 if(mOnProgressListener != null) {
 mOnProgressListener.onProgress(resource, byteCount, contentLength);
 }
 }
 outputStream.flush();
 }
 }
 public interface OnProgressListener {
 void onProgress(Resource resource, int downloaded, int downloadSize);
 }
}
</httpmessageconverter<?></httpmessageconverter<?>

licensed under cc by-sa 3.0 with attribution.