사용자가 사이트에 사진을 업로드하고 이미 업로드 한 파일을 이미지로 표시 할 수있는 라켓 웹 서버용 서블릿을 만들려고합니다. 같은 페이지. 사진을 디스크 나 메모리의 임시 파일에 저장하는 대신 PostgreSQL 데이터베이스 안팎으로 직접 스트리밍하고 싶습니다. 가능한가? 그렇다면 최선의 방법은 무엇입니까? 상태없는 서블릿으로 수행 할 수 있습니까? 어떤 도움이라도 대단히 감사합니다!Racket Server & PostgreSQL - 메모리 또는 디스크에 저장하지 않고 BLOB 업로드/다운로드
3
A
답변
4
해야합니다. PLaneT에서 db
package을 추천합니다 (필자가 작성했기 때문에). 온라인으로 the docs을 (를) 읽을 수 있습니다.
PostgreSQL 테이블은 이미지 내용에 대해 bytea
필드를 가져야합니다. 라켓 쪽에서는 바이트 문자열로 표시됩니다.
서블릿에서 이미지 내용이있는 response/full
구조를 반환해야합니다. 리턴 코드, MIME 유형 등을 직접 처리해야합니다. (설명서의 예를 참조하십시오.)
1
과학의 이름으로 나는 내 자신의 질문에 대답의 절반을 게시하고 있습니다. 이 페이지에는 이미 데이터베이스에있는 이미지가 표시됩니다. 업로드 페이지는 아직 열려있는 질문입니다.
라이언 컬페퍼 (Ryan Culpepper)는 여기에 게시 된 것 이상의 개인적인 서신에서 나를 도왔습니다. 나는 그의 도움에 감사한다. 흑 마술처럼 보일지도 모르는 모든 것들이 그에게서 나오고 모든 어색한 멍청이가 내 것이됩니다. 코드 개선 방법에 대한 모든 제안에 감사드립니다.
#lang racket
#|
================================================================================================================
We are assuming that the PostgreSQL database we are connecting to
has a table "person" with columns
"id", "firstname", "lastname" and "portrait".
The "portrait" column contains the OID of a BLOB
that stores the image file we want to display.
Suppose further that the table "person" has a legitimate entry with
id=22, firstname="John", lastname="Doe"
Then the page
http://127.0.0.1/page/22
should display greetings "Hello, John Doe!"
and show the portrait of the person below the greeting.
The portrait itself should be at
http://127.0.0.1/portrait/22.jpg
The program should be run via Racket -t "<filename>"
after defining the environment variables
"DB_USER", "DB_NAME", "DB_PORT", "DB_PASSWORD".
================================================================================================================
|#
(require
web-server/servlet
web-server/servlet-env
web-server/dispatch
web-server/stuffers/hmac-sha1
web-server/http
web-server/http/response-structs
(planet ryanc/db:1:4)
(planet ryanc/db:1:4/util/connect)
net/base64)
;---------------------------------------------------------------------------------------------------------------
; response
;---------------------------------------------------------------------------------------------------------------
(define (start given-request)
(site-dispatch given-request))
(define-values (site-dispatch given-request)
(dispatch-rules
[("page" (integer-arg)) show-page]
[("portrait" (string-arg)) show-portrait]))
(define (show-page given-request given-person-id)
(let* ([db-person_firstname_lastname
(query-maybe-row my-connection
"SELECT firstname, lastname FROM person WHERE id = $1"
given-person-id)]
[my-firstname (vector-ref db-person_firstname_lastname 0)]
[my-lastname (vector-ref db-person_firstname_lastname 1)])
(response/xexpr
`(html ([xmlns "http://www.w3.org/1999/xhtml"])
(head
(title "Page with a portrait"))
(body
(div ([id "greetings"])
,(string-append
"Hello, " my-firstname " " my-lastname "! "))
(img ( [src ,(string-append "/portrait/"
(number->string given-person-id) ".jpg")])))))))
(define (show-portrait given-request given-portrait-file)
(let* ([my-user-id (car (regexp-match #rx"^([0-9]+)"
given-portrait-file))]
[my-portrait-oid (query-value my-connection
"SELECT portrait FROM person WHERE id = $1"
(string->number my-user-id))]
[STREAMOUT_CHUNK_SIZE 1000]
[INV_READ #x00040000])
(response
200 ; code
#"Okay" ; message
(current-seconds) ; seconds
#"image/jpeg" ; mime type
empty ; headers
(lambda (given-output-stream) ; body generator
(start-transaction my-connection)
(define object-descriptor
(query-value my-connection
"SELECT LO_OPEN($1, $2)" my-portrait-oid INV_READ))
(define (stream-next-chunk)
(begin
(define my-next-chunk
(query-value my-connection
"SELECT LOREAD($1, $2)"
object-descriptor STREAMOUT_CHUNK_SIZE))
(if (> (bytes-length my-next-chunk) 0)
(begin
(write-bytes my-next-chunk given-output-stream)
(stream-next-chunk)
#t)
#f)))
(stream-next-chunk)
(commit-transaction my-connection)))))
;---------------------------------------------------------------------------------------------------------------
; database connection
;---------------------------------------------------------------------------------------------------------------
(define my-connection
(virtual-connection
(connection-pool
(lambda()
(eprintf "(Re)establishing database connection...\n")
(postgresql-connect
#:user (getenv "DB_USER")
#:database (getenv "DB_NAME")
#:port (string->number (getenv "DB_PORT"))
#:socket #f
#:password (getenv "DB_PASSWORD")
#:allow-cleartext-password? #f
#:ssl 'optional ; other choices: 'yes 'no
)))))
;---------------------------------------------------------------------------------------------------------------
; servlet parameters
;---------------------------------------------------------------------------------------------------------------
(serve/servlet start
#:command-line? #t ; #t to use serve/servlet in a start up script for a Web application, and don't want a browser opened or the DrRacket banner printed
#:connection-close? #f ; #t to close every connection after one request. (Otherwise, the client decides based on what HTTP version it uses.)
#:launch-browser? #f
#:quit? #f ; #t makes the URL "/quit" end the server
#:banner? #t ; #t to print an informative banner
#:listen-ip #f ; give an IP to accept connections from external machines
#:port 80 ; 443 is the default for SSL, 80 - for open connections
#:servlet-regexp #rx"" ; #rx"" captures top-level requests
#:stateless? #t
#:server-root-path ; where the server files are rooted, default=(the distribution root)
(build-path ".")
#:ssl? #f
#:log-file (build-path "server.log"))
관련 문제
- 1. 어셈블리를 디스크에 저장하지 않고 C# 식을 컴파일하고 실행할 수 있습니까?
- 2. bash에서 디스크에 blob 필드 저장하기
- 3. 디스크에 이미지를 저장하지 않고 JasperReport를 HTML로 내보내는 방법?
- 4. s3에 저장된 이미지를 하드 디스크에 저장하지 않고 표시하는 방법은 무엇입니까?
- 5. 디스크 공간을 계산하면 문자열을 디스크에 저장하지 않고 사용합니다.
- 6. 디스크에 저장하지 않고 생성 된 XML 파일을 전송하십시오.
- 7. Ruby - 디스크에 저장하지 않고 Mechanize :: File 응답으로 작업하기
- 8. Postgresql, JDBC 및 스트리밍 BLOB
- 9. InnoDB는 어떤 값을 디스크에 저장하지 않습니까?
- 10. 메모리 데이터베이스에있는 PostgreSQL
- 11. BLOB 저장소 - 100GB 이상, MySQL, SQLite 또는 PostgreSQL + Python
- 12. outfile을 선택하여 파일에 저장하지 않고 blob로 저장하십시오.
- 13. xml 파일을 저장하지 않고
- 14. 디스크에 메모리 내 데이터베이스 저장
- 15. 미디어 파일을 해독하고 HDD에 저장하지 않고 재생합니다.
- 16. 저장하지 않고 파일 업로드 내용을 이진 파일로 변환
- 17. "select"in Racket
- 18. 서버에 저장하지 않고 파일을 다운로드하십시오.
- 19. Racket REPL over TCP
- 20. xml 파일을 디스크에 저장하지 않고 openxml 파일에서 XML 문서를로드하는 방법은 무엇입니까?
- 21. 저장하지 않고 ActiveRecord 유효성 검사하기
- 22. 저장하지 않고 Infopath 양식을 업그레이드하십시오.
- 23. 이미지를 저장하지 않고 브라우저로 전송
- 24. InAppSettingsKit을 설정 앱에 저장하지 않고
- 25. 서버에 저장하지 않고 파일을 읽으십니까?
- 26. 디스크에 저장하지 않고 다른 탭/창에서 html 파일을 미리 보는 방법은 무엇입니까?
- 27. Imagick (Imagemagick on PHP) : 먼저 디스크에 저장하지 않고 파일을 제공 하시겠습니까?
- 28. 먼저 디스크에 저장하지 않고 ExcelWorkBook에서 byte []를 가져 오는 방법이 있습니까
- 29. CodeIgniter :: 하드 디스크에 저장하지 않고 이미지의 크기를 조정하고 워터 마킹하는 방법
- 30. C++ 디스크에 저장하지 않고 문자열에 웹 페이지를 다운로드하는 방법 - URLDownloadToFile이 작동하지 않습니다.